#include "watchermainwindow.h"
#include "makefilewidget.h"
#include "ui_watchermainwindow.h"
#include <QDebug>
#include <QDir>
#include <QFileSystemWatcher>
#include <QProcess>
#include <QSettings>
#include <QSplitter>
#include <qlistwidget.h>
#include <qprocess.h>

QStringList findMakefiles(const QString& directoryPath)
{
    QStringList makefilePaths;

    // 获取目录
    QDir dir(directoryPath);
    // 遍历当前目录及其子目录
    QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
    for (const QFileInfo& fileInfo : fileInfoList) {
        if (fileInfo.isDir()) {
            // 如果是目录，递归查找
            makefilePaths.append(findMakefiles(fileInfo.absoluteFilePath()));
        } else if (fileInfo.isFile() && fileInfo.fileName() == "Makefile") {
            // 如果是 "Makefile"，保存路径
            QString relativePath = fileInfo.absolutePath();
            makefilePaths.append(relativePath);
        }
    }

    return makefilePaths;
}

WatcherMainWindow::WatcherMainWindow(QWidget* parent)
    : QMainWindow(parent)
    , ui(new Ui::WatcherMainWindow)
{
    ui->setupUi(this);
    sp = new QSplitter(Qt::Vertical, ui->widget);
    sp->addWidget(ui->listWidget);
    sp->addWidget(ui->textBrowser);
    m_make = new QProcess(this);
    m_make->setProcessChannelMode(QProcess::MergedChannels);
    connect(m_make, &QProcess::readyRead, this, [=]() {
        QByteArray data = m_make->readAll();
        ui->textBrowser->append(data);
    });
    connect(m_make, &QProcess::errorOccurred, this,
        [=](QProcess::ProcessError err) {
            log("Error: " + QString::number(err));
        });
    connect(
        m_make, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
        this, [=](int code, QProcess::ExitStatus exitStatus) {
            QString ret = QString("exitCode: %1, exitStatus: %2").arg(code).arg(exitStatus);
            log(ret);
            if (code == 0 and exitStatus == QProcess::ExitStatus::NormalExit) {
                QString wkdir = m_make->workingDirectory();
                updateCount(wkdir);
            }
        });

    // listen
    m_listen = new QProcess(this);
    m_listen->start("./listen");
    connect(m_listen, &QProcess::readyRead, this, [=]() {
        QByteArray data = m_listen->readAll();
        ui->textBrowser->append(data);
        updateCount(data);
    });

    connect(m_listen, &QProcess::errorOccurred, this,
        [=](QProcess::ProcessError err) {
            log("Error: " + QString::number(err));
        });
    //    fsw = new QFileSystemWatcher(this);
    //    connect(fsw, &QFileSystemWatcher::directoryChanged, this, [=](){

    //    });
    connect(ui->pushButton, &QPushButton::clicked, this, [=]() {
        QSettings set(QCoreApplication::applicationDirPath() + "/config.ini",
            QSettings::Format::IniFormat, this);
        QString build = set.value("build", "").toString();
        m_buildPath = build;
        m_sourcePath = set.value("source", "").toString();
        log(m_buildPath);
        log(m_sourcePath);
        if (build.isEmpty()) {
            log("构建目录为空");
            return;
        }
        if (m_sourcePath.isEmpty()) {
            log("源码目录为空");
            return;
        }
        QDir d_build(build);
        if (!d_build.exists()) {
            log("构建目录不存在");
            return;
        }

        ui->listWidget->clear();
        QStringList paths = findMakefiles(build);
        for (auto& path : paths) {
            QString relative = path.mid(m_buildPath.length());
            // if (relative.isEmpty())
            //   continue;
            add(relative);
        }
    });

    connect(ui->pb_sort, &QPushButton::clicked, this, [=]() {
        QList<QListWidgetItem*> items;
        for (int i = 0; i < ui->listWidget->count(); i++) {
            items.append(ui->listWidget->item(i));
        }
        std::sort(items.begin(), items.end(),
            [=](QListWidgetItem* a, QListWidgetItem* b) {
                auto wa = qobject_cast<MakefileWidget*>(ui->listWidget->itemWidget(a));
                auto wb = qobject_cast<MakefileWidget*>(ui->listWidget->itemWidget(b));
                return wa->Count() < wb->Count();
            });
        ui->listWidget->clear();
        for (auto it : items) {
            ui->listWidget->addItem(it);
        }
    });

    connect(ui->listWidget, &QListWidget::itemDoubleClicked, this,
        [=](QListWidgetItem* it) {
            auto w = qobject_cast<MakefileWidget*>(ui->listWidget->itemWidget(it));
            QString dirpath = m_buildPath + w->path();
            QString cmd = "make -j6";
            runCmd(dirpath, cmd);
        });
}

WatcherMainWindow::~WatcherMainWindow()
{
    m_listen->kill();
    m_listen->waitForFinished();
    delete ui;
}

void WatcherMainWindow::add(QString path)
{
    QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
    MakefileWidget* mw = new MakefileWidget(this);
    mw->setPath(path);
    ui->listWidget->setItemWidget(item, mw);
    item->setSizeHint(mw->size());
}

void WatcherMainWindow::log(QString msg) { ui->textBrowser->append(msg); }

void WatcherMainWindow::runCmd(QString dir, QString cmd)
{
    m_make->kill();
    m_make->waitForFinished();
    ui->textBrowser->clear();
    log(cmd);
    m_make->setWorkingDirectory(dir);
    m_make->start(cmd);
}

void WatcherMainWindow::showEvent(QShowEvent* event)
{
    sp->resize(ui->widget->size());
    sp->show();
    QWidget::showEvent(event);
}

void WatcherMainWindow::resizeEvent(QResizeEvent* event)
{
    sp->resize(ui->widget->size());
    sp->show();
    QWidget::resizeEvent(event);
}

void WatcherMainWindow::updateCount(QString path)
{
    int c = -2;
    // make finish
    if (path.contains(m_buildPath)) {
        path = path.mid(m_buildPath.length());
        c = 0;
    } else if (path.contains(m_sourcePath)) {
        // listen
        path = path.mid(m_sourcePath.length());
        c = 1;
    } else {
        return;
    }
    for (int i = 0; i < ui->listWidget->count(); i++) {
        auto item = qobject_cast<MakefileWidget*>(
            ui->listWidget->itemWidget(ui->listWidget->item(i)));
        item->setCount(c, path);
    }
}
